package org.orbis.memoryblock.appendix;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import org.msgpack.MessagePackObject;
import org.msgpack.object.ArrayType;
import org.msgpack.object.IntegerType;
import org.msgpack.object.RawType;
import org.orbis.constants.Constants;
import org.orbis.memoryblock.MemoryBlock;
import org.orbis.toolbox.ByteConverter;

/** This block stores contents without analyze (i.e. URL, description)
 * 
 * @author fujisaka_yusuke */
public class AppendixBlock extends MemoryBlock{
	public static final int OPT_TYPE = 0;
	public static final int OPT_REF = 1;
	public static final int OPTSIZE = 2;

	public AppendixBlock(ByteBuffer body, int bodySize, int ID, int repBlock){
		super(body, bodySize, ID, Constants.MEMORY_TYPE_APPENDIX, repBlock);
	}

	public AppendixBlock(ByteBuffer existingBody){
		super(existingBody);
	}

	public AppendixPackage read(int ptr){
		AppendixPackage pkg = AppendixPackage.setPackage().cluster(getCluster());
		int strlen = getInt(ptr, STRLEN);
		ptr += STRLEN;
		pkg.stringRaw(read(ptr, strlen));
		return pkg;
	}

	public int write(int ptr, AppendixPackage pkg){
		setInt(ptr, STRLEN, pkg.getStrLength());
		ptr += STRLEN;
		store(pkg.getStringRaw(), ptr);
		return pkg.length();
	}

	public synchronized int getNewPointer(AppendixPackage pkg){
		if(bodyVacancy < pkg.length()) return -1;
		bodyVacancy -= pkg.length();
		return bodySize - bodyVacancy - pkg.length();
	}

	public static byte[] createByteArray(String str) throws IOException{
		byte[] barray = str.getBytes("UTF-8");
		ByteArrayOutputStream stream = new ByteArrayOutputStream();

		stream.write(ByteConverter.intToByte(barray.length, STRLEN));
		stream.write(barray);

		return stream.toByteArray();
	}

	public byte[] getData() throws IOException{
		ByteArrayOutputStream stream = new ByteArrayOutputStream(this.bodySize + 4);

		stream.write(getOptionByteStream());
		stream.write(this.read(0, this.bodySize));

		return stream.toByteArray();
	}

	public void setData(byte[] array){
		setBody(array, 0, bodySize, 0);
	}

	public int getSupplementIndex(){
		return option[OPT_TYPE];
	}

	@Override
	public int getOptionSize(){
		return OPTSIZE;
	}

	@Override
	public byte[] getOptionByteStream(){
		return ByteConverter.intToByte(option[OPT_TYPE], 4);
	}

	@Override
	public int getOption(int index){
		if(index >= OPTSIZE) return -1;
		return option[index];
	}

	@Override
	public void setOption(int index, int value){
		if(index >= OPTSIZE) return;
		option[index] = value;
	}

	@Override
	public String getClassName(){
		return new String("Appendix");
	}
	
	@Override
	public ArrayType toArrayType(){
		MessagePackObject[] objectArray = new MessagePackObject[4];
		this.setHeader();
		objectArray[0] = IntegerType.create(getID());
		objectArray[1] = IntegerType.create(getCluster());
		objectArray[2] = IntegerType.create(getType());
		objectArray[3] = IntegerType.create(getOption(OPT_TYPE));
		objectArray[4] = RawType.create(readAllByteArray());
		
		return ArrayType.create(objectArray);
	}

	public int setReferenceCount(int difference){
		option[OPT_REF] += difference;
		return option[OPT_REF];
	}
}
